package com.kevin.table;

import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;

import com.kevin.sql.DataType;
import com.kevin.utils.StaticTool;
import com.kevin.utils.common.KnCommonUtils;

import sun.misc.BASE64Encoder;

public class MDataCell {
	private MCellValue cellValue;
	private String stringValue;
	/**
	 * 单元格结构
	 */
	private transient MCellStruct cellstruct;

	MDataCell(MCellStruct dataStruct) {
		init(dataStruct, null);
	}

	MDataCell(MCellStruct dataStruct, Object value) {
		init(dataStruct, value);
	}

	/**
	 * 初始化
	 * 
	 * @param dataStruct
	 * @param value
	 */
	private void init(MCellStruct dataStruct, Object value) {
		cellstruct = dataStruct;
		if (value != null) {
			cellValue = new MCellValue();
			setValue(value);
		}
	}

	private boolean isAllowChangeState = true;
	private boolean isNewValue = false;
	private Object newValue = null;

	private void checkNewValue() {
		if (isNewValue) {
			isNewValue = false;
			fixValue(newValue);
			newValue = null;
			isAllowChangeState = true;// 恢复可设置状态。
		}
	}

	/**
	 * 修改值的状态
	 * 
	 * @param value
	 *            新值
	 */
	private void fixValue(Object value) {
		if (value == null) // 如果新值为空
		{
			// 原值也为空，则修改状态为未改变
			if (getCellValue().isNull) {
				getCellValue().state = MCellValue.NONE;
			} // 原值不为空，则修改值和状态
			else {
				if (isAllowChangeState) {
					getCellValue().state = MCellValue.SETCHANGE;
				}
				getCellValue().value = null;
				getCellValue().isNull = true;
				stringValue = StringUtils.EMPTY;
			}
		} else {
			stringValue = value.toString();
			int groupID = DataType.getGroup(cellstruct.getSqlType());
			// 上边判断了不是null
			// 如果不是字符型，并且是空值
			if (stringValue.equals(StringUtils.EMPTY) && groupID > 0) {
				getCellValue().value = null;
				getCellValue().isNull = true;
				return;
			}
			value = changeValue(value, cellstruct.valueType, groupID);
			if (value == null) {
				return;
			}

			if (!getCellValue().isNull && (getCellValue().value.equals(value)
					|| (groupID != 999 && getCellValue().value.toString().equals(stringValue)))) // 对象的比较值，用==号则比例引用地址。
			{
				if (isAllowChangeState) {
					getCellValue().state = MCellValue.SETSAME;
				}
			} else {
				getCellValue().value = value;
				getCellValue().isNull = false;
				if (isAllowChangeState) {
					getCellValue().state = MCellValue.SETCHANGE;
				}
			}

		}
	}

	/**
	 * 值的数据类型转换。
	 * 
	 * @param value
	 *            要被转换的值
	 * @param convertionType
	 *            要转换成哪种类型
	 * @param groupID
	 *            数据库类型的组号
	 * @return
	 */
	Object changeValue(Object value, Class<?> clazz, int groupID) {
		stringValue = String.valueOf(value);
		if (value == null) {
			getCellValue().isNull = true;
			stringValue = StringUtils.EMPTY;// 要不然 就会 是 "null"
			return value;
		}
		if (groupID > 0 && getStringValue().equals(StringUtils.EMPTY)) {
			getCellValue().isNull = true;
			return null;
		}
		// 上边都是判断，下边才是真的转换
		try {
			// 数字型
			if (groupID == 1) {
				switch (getStringValue()) {
				case "正无穷大":
					stringValue = "Infinity";
					break;
				case "负无穷大":
					stringValue = "-Infinity";
					break;
				}
			}
			// 如果不同才进行转换（废话）
			if (value.getClass() != clazz) {
				switch (groupID) {
				case 0:// 字母型
					// if (cellstruct.getSqlType() == Types.TIME)//time类型的特殊处理。
					// {
					// String[] items = StringUtils.split(getStringValue()," ");
					// if (items.length > 1)
					// {
					// stringValue = items[1];
					// }
					// }
					value = getStringValue();
					break;
				case 1:// 数字型
					switch (getStringValue().toLowerCase()) {
					case "true":
						value = 1;
						break;
					case "false":
						value = 0;
						break;
					case "infinity":
						value = Double.POSITIVE_INFINITY;
						break;
					case "-infinity":
						value = Double.NEGATIVE_INFINITY;
						break;
					default:
						value = valueNullType(clazz, value);
					}
					break;
				case 2:// 日期型
					switch (StringUtils.stripEnd(getStringValue().toLowerCase(), ")(")) {
					case "now":
					case "getdate":
					case "current_timestamp":
						value = new Date();
						break;
					default:
						value = valueNullType(clazz, value);
						if (cellstruct.getSqlType() == Types.TIMESTAMP) {
							SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
							stringValue = sdf.format(value);
						} else if (cellstruct.getSqlType() == Types.DATE) {
							SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
							stringValue = sdf.format(value);
						} else if (cellstruct.getSqlType() == Types.TIME) {
							SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
							stringValue = sdf.format(value);
						}
						break;
					}
					break;
				case 3:// bool返回
					switch (getStringValue().toLowerCase()) {
					case "yes":
					case "true":
					case "1":
					case "on":
					case "是":
						value = true;
						break;
					case "no":
					case "false":
					case "0":
					case "":
					case "否":
					default:
						value = false;
						break;
					}
					break;
				default:
					value = valueNullType(clazz, value);
					break;
				}
			}
		} catch (Exception err) {
			value = null;
			getCellValue().value = null;
			getCellValue().isNull = true;
			// String msg = "ChangeType
			// Error：ColumnName【"+cellstruct.getColumnName()+"】("+cellstruct.valueType.getTypeName()+")
			// ， Value：【{"+stringValue+"}】\r\n";
			stringValue = null;
		}
		return value;
	}

	private Object valueNullType(Class<?> convertType, Object value) throws Exception {
		if (convertType.getName().endsWith("[]")) {
			value = new BASE64Encoder().encode(stringValue.getBytes("UTF-8"));
			stringValue = "System.Byte[]";
		} else {
			value = StaticTool.changeType(value, convertType);
		}
		return value;
	}

	/**
	 * 判断单元格是否为空
	 * 
	 * @return
	 */
	public boolean isEmpty() {
		checkNewValue();
		return isNull() || getStringValue().length() == 0;
	}

	public boolean isNull() {
		checkNewValue();
		return getCellValue().isNull;
	}

	/**
	 * 单元格的值，内部属性
	 * 
	 * @return
	 */
	private MCellValue getCellValue() {
		if (cellValue == null) {
			cellValue = new MCellValue();
		}
		return cellValue;
	}

	public String getStringValue() {
		checkNewValue();
		return stringValue;
	}

	/**
	 * 取值
	 * 
	 * @return
	 */
	public Object getValue() {
		checkNewValue();
		return getCellValue().value;
	}

	/**
	 * 赋值
	 * 
	 * @param value
	 */
	public void setValue(Object value) {
		this.newValue = value;
		isNewValue = true;
		isAllowChangeState = true;
	}

	/**
	 * 目前先不可读
	 * 
	 * @param sourceValue
	 */
	void setSourceValue(Object sourceValue) {
		getCellValue().value = sourceValue;
	}

	/**
	 * 列名（只读属性）
	 * 
	 * @return
	 */
	public String getColumnName() {
		return cellstruct.getColumnName();
	}

	/**
	 * 获取单元格的结构（只读属性）
	 * 
	 * @return
	 */
	public MCellStruct getCellstruct() {
		return cellstruct;
	}

	public Integer getState() {
		checkNewValue();
		return getCellValue().state;
	}

	public void setState(Integer state) {
		if (isNewValue) {
			isAllowChangeState = false;
		}
		getCellValue().state = state;
	}

	/**
	 * 将值重置为空
	 */
	public void Clear() {
		isNewValue = false;
		newValue = null;
		getCellValue().value = null;
		getCellValue().state = MCellValue.NONE;
		getCellValue().isNull = true;
		stringValue = null;
	}

	@SuppressWarnings("unchecked")
	public <T> T get(Class<T> t) {
		if (getCellValue().isNull) {
			return KnCommonUtils.<T> getDefault(t);
		}
		return (T) changeValue(getCellValue().value, t, DataType.getGroup(getCellstruct().getSqlType()));
	}
}
